package com.gaga.console.core.service.impl;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gaga.common.constant.BvConstants;
import com.gaga.common.enums.*;
import com.gaga.common.result.AiModelResult;
import com.gaga.common.result.ReplaceTextResult;
import com.gaga.common.utils.AudioPlayerUtils2;
import com.gaga.common.utils.NumberConverter;
import com.gaga.common.utils.TemplateReplacer;
import com.gaga.console.base.entity.sse.PushMessageDto;
import com.gaga.console.base.utils.RestUtils;
import com.gaga.console.base.utils.SseEmitterServerUtils;
import com.gaga.console.core.entity.dto.BatchTtsDto;
import com.gaga.console.core.entity.dto.ChatDto;
import com.gaga.console.core.entity.dto.TextToSpeechDto;
import com.gaga.console.core.entity.dto.TextToSpeechFrontDto;
import com.gaga.console.core.entity.vo.ModelVO;
import com.gaga.console.core.entity.vo.TextToSpeechVo;
import com.gaga.console.core.service.*;
import com.gaga.console.core.service.impl.multimodel.ModelFactory;
import com.gaga.console.core.service.impl.multimodel.ModelHandler;
import com.gaga.console.core.service.impl.multimodel.result.SwitchResult;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileNotFoundException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author liujia
 * @since 2025-03-27
 */
@Service
public class BvModelServiceImpl implements BvModelService {

    private static final Logger log = LoggerFactory.getLogger(BvModelServiceImpl.class);

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private BvAudioPlayService bvAudioPlayService;

    @Autowired
    private AudioPlayQueueService audioPlayQueueService;

    @Autowired
    private BvAiModelService bvAiModelService;

    @Autowired
    private BvConfigService bvConfigService;

    @Autowired
    private AssistantService assistantService;

    private String encryptModelPath = "";

    private String modelWorkspacePath = "";

    private String ttsUrl = "";

    private String ttsUrl9881 = "";

    private String sovitsUrl = "";

    private String gptUrl = "";

    private String modelPath = "";

    private String modelControlUrl = "";

    private final AtomicBoolean isStart = new AtomicBoolean(true);

    @PostConstruct
    public void init() {
        modelPath = sysConfigService.getConfigValueByKey(BvConstants.MODEL_PATH);
        sovitsUrl = sysConfigService.getConfigValueByKey(BvConstants.MODEL_URL_SETSOVITS);
        gptUrl = sysConfigService.getConfigValueByKey(BvConstants.MODEL_URL_SETGPT);

        encryptModelPath = sysConfigService.getAbsolutePathByKey(BvConstants.ENCRYPT_MODEL_PATH);
        modelWorkspacePath = sysConfigService.getAbsolutePathByKey(BvConstants.MODEL_WORKSPACE_PATH);
        ttsUrl = sysConfigService.getConfigValueByKey(BvConstants.MODEL_URL_TTS);
        ttsUrl9881 = sysConfigService.getConfigValueByKey(BvConstants.MODEL_URL_TTS_9881);
        modelControlUrl = sysConfigService.getConfigValueByKey(BvConstants.modelUrlControl);
    }

    @Override
    public List<ModelVO> listModel() {

        List<ModelVO> modelList = new ArrayList<>();
        if (StringUtils.isBlank(encryptModelPath)) {
            return modelList;
        }

        File directory = new File(encryptModelPath);

        // 检查路径是否存在且是目录
        if (!directory.exists() || !directory.isDirectory()) {
            return modelList;
        }

        File[] files = directory.listFiles();
        if (files == null) {
            return modelList;
        }

        for (File file : files) {
            if (file.isDirectory()) {
                ModelVO modelVO = new ModelVO();
                modelVO.setModelName(file.getName());
                modelList.add(modelVO);
            }
        }
        return modelList;
    }

    @Override
    public void switchModel(PlayerType playerType, String modelName) {

        if (StringUtils.isBlank(modelName)) {
            return;
        }
        if (StringUtils.isBlank(modelPath) || StringUtils.isBlank(modelWorkspacePath)) {
            return;
        }
        ModelHandler handler = ModelFactory.getHandler(playerType, sysConfigService, bvConfigService, modelPath, sovitsUrl, gptUrl);
        String currentModel = handler.getCurrentModel();

        //如果切换的模型和当前模型一致，则不需要切换
        if (modelName.equals(currentModel)) {
            return;
        }

        try {
            assistantService.startModel();
        } catch (FileNotFoundException e) {
            log.error("切换模型时启动模型失败");
        }

        //切换的模型需要解密,直播中不需要解密
        bvAudioPlayService.decryptModel(Arrays.asList(modelName));

        File modelDirectory = new File(modelWorkspacePath + File.separator + modelPath + File.separator + modelName);

        // 检查路径是否存在且是目录
        if (!modelDirectory.exists() || !modelDirectory.isDirectory()) {
            return;
        }

        File[] files = modelDirectory.listFiles();
        if (files == null) {
            return;
        }

        //调用两个接口切换模型
        SwitchResult switchCkptResult = handler.switchCkpt(files, modelName);
        if (!switchCkptResult.getIsSuceess()) {
            return;
        }

        SwitchResult switchPthResult = handler.switchPth(files, modelName);
        if (!switchPthResult.getIsSuceess()) {
            return;
        }

        //更新切换模型后的引用音频路径
        handler.updateRefAudioPath(files, modelName);

        //更新切换模型后的prompt文本
        handler.updatePromptText(files, modelName);

        //更新当前播放的模型
        handler.updateCurrentModel(modelName);
    }

    @Override
    public void testListening(PlayerType playerType, String modelName) throws Exception {

//        List<String> selectModelNameList = bvConfigService.getSelectModelNameList();
//        bvAudioPlayService.decryptModel(selectModelNameList);

        //开启模型
//        assistantService.startModel();
//
//        switchModel(playerType, modelName);

        String modelPath = sysConfigService.getAbsolutePathByKey(BvConstants.ENCRYPT_MODEL_PATH);

        String audioPath = modelPath + File.separator + modelName + File.separator + "ck.wav";

        AudioPlayerUtils2 player = new AudioPlayerUtils2();
        player.init(audioPath, bvConfigService.getSelectDeviceName(), playerType);
        player.play();
//
//        ConfigDto configDto = bvConfigService.getConfig();
//
//        String text = "你好.我是AI直播助手.很高兴见到你.欢迎新到直播间的家人们";
//
//        String generateAudioPath = sysConfigService.getAbsolutePathByKey(BvConstants.GENERATE_AUDIO_PATH);
//
//        //生成音频文件路径
//        if (!generateAudioPath.endsWith(File.separator)) {
//            generateAudioPath = generateAudioPath + File.separator;
//        }
//        generateAudioPath = generateAudioPath + "试听" + File.separator + modelName + BvConstants.WAV_FORMAT;
//
//        TextToSpeechFrontDto textToSpeechFrontDto = BvAudioPlayServiceImpl.getTextToSpeechFrontDto(text, configDto.getModelSetting());
//        textToSpeechFrontDto.setPlayerType(playerType);
//
//        //生成音频文件路径
//        textToSpeechFrontDto.setGenerateAudioPath(generateAudioPath);
//        if (PlayerType.ANCHOR.equals(playerType)) {
//            textToSpeechFrontDto.setPromptText(sysConfigService.getConfigValueByKey(BvConstants.PROMPT_TEXT_9876));
//            textToSpeechFrontDto.setRefAudioPath(sysConfigService.getConfigValueByKey(BvConstants.REF_AUDIO_PATH_9876));
//        } else if (PlayerType.ASSISTANT.equals(playerType)) {
//            textToSpeechFrontDto.setPromptText(sysConfigService.getConfigValueByKey(BvConstants.PROMPT_TEXT_9875));
//            textToSpeechFrontDto.setRefAudioPath(sysConfigService.getConfigValueByKey(BvConstants.REF_AUDIO_PATH_9875));
//        }
//
//        textToSpeechFrontDto.setScriptType(ScriptType.MAIN_AUDIO);
//        TextToSpeechVo textToSpeechVo = textToSpeech(textToSpeechFrontDto);


    }

    @Override
    @Deprecated
    public void restartModel() {
        //--模型接口不支持
        RestUtils.get(modelControlUrl + "?command=restart");
    }

    @Override
    @Deprecated
    public void exitModel() {
//        --模型接口不支持
        RestUtils.get(modelControlUrl + "?command=exit");
    }

    @Override
    public TextToSpeechVo textToSpeech(TextToSpeechFrontDto dto) throws Exception {

        TextToSpeechVo textToSpeechVo = new TextToSpeechVo();

        String openDoubleModelStr = sysConfigService.getConfigValueByKey(BvConstants.SINGLE_DOUBLE_MODEL);
        SingleDoubleModelType byCode = SingleDoubleModelType.getByCode(openDoubleModelStr);

        TextToSpeechDto textToSpeechDto = new TextToSpeechDto();
        BeanUtils.copyProperties(dto, textToSpeechDto);
        if (SingleDoubleModelType.COMPATIBLE.equals(byCode)) {
            textToSpeechDto.setTextLang("zh");
            textToSpeechDto.setPromptLang("zh");
            textToSpeechDto.setTextSplitMethod("cut2");
        }

        int leftBraceCount = StringUtils.countMatches(textToSpeechDto.getText(), "{");
        int rightBraceCount = StringUtils.countMatches(textToSpeechDto.getText(), "}");
        if (leftBraceCount != rightBraceCount) {
            return null;
        }
        //替换话术文本中的参数
        Integer queueSize = 2;
        if (dto.getScriptType() == ScriptType.MAIN_AUDIO) {
            queueSize = audioPlayQueueService.getQueueSize(PlayerType.ANCHOR) + 2;
        }

        ReplaceTextResult replaceTextResult = TemplateReplacer.replaceParameters(textToSpeechDto.getText(), dto.getUserName(), bvAudioPlayService.getUserCount(), queueSize);
        textToSpeechDto.setText(replaceTextResult.getText());
        textToSpeechVo.setFutureTime(replaceTextResult.getFutureTime());
        textToSpeechVo.setOldText(textToSpeechDto.getText());
        if (dto.getSmartPolish() || dto.getSmartQA()) {
            //智能回复
            ChatDto chatDto = new ChatDto();
            chatDto.setModelId(dto.getModelId() == null ? 1L : dto.getModelId());
            chatDto.setMessage(textToSpeechDto.getText());
            chatDto.setBlockWords(dto.getBlockWords());
            chatDto.setLiveRoomDesc(dto.getLiveRoomDesc());
            chatDto.setToken(dto.getToken());

            if (dto.getSmartQA()) {
                //开启智能回复
                chatDto.setPolishOrQaType(PolishOrQaType.QA);
                chatDto.setMessage(dto.getProblemText());
                chatDto.setAnchorName(dto.getAnchorName());
                chatDto.setUserCallName(dto.getUserCallName());
            } else {
                chatDto.setPolishOrQaType(PolishOrQaType.POLISH);
            }

            AiModelResult aiModelResult = bvAiModelService.callWithMessage(chatDto);
            if (aiModelResult.getIsSuceess() && StringUtils.isNotBlank(aiModelResult.getResult())) {
                if (dto.getSmartPolish() || dto.getSmartQA()) {
                    textToSpeechDto.setText(TemplateReplacer.replacePolishText(aiModelResult.getResult(), dto.getUserName(), dto.getUserCallName()));
                } else {
                    textToSpeechDto.setText(TemplateReplacer.replacePolishText(aiModelResult.getResult(), null, null));
                }
            }
            if (dto.getSmartQA() && !aiModelResult.getIsSuceess()) {
                textToSpeechDto.setText(null);
            }
        } else {
            //润色前的话术需要数字转中文
            textToSpeechDto.setText(NumberConverter.convertAmountInText(textToSpeechDto.getText()));
        }
        if (StringUtils.isBlank(textToSpeechDto.getText())) {
            return textToSpeechVo;
        }

        //是否复读问题
        if (dto.getRepeatProblem() && StringUtils.isNotBlank(dto.getProblemText())) {
            String problemText = dto.getProblemText().replaceAll("\\[[^\\]]*\\]", "");
            problemText = problemText.replaceAll(
                    "[^a-zA-Z0-9\\p{P}\\p{script=Han}]",
                    ""
            );
            textToSpeechDto.setText(problemText + "." + textToSpeechDto.getText());
        }

        PushMessageDto pushMessageDto = new PushMessageDto();
        pushMessageDto.setMessage(textToSpeechDto.getText());

        switch (dto.getScriptType()) {
            case INSERT_AUDIO:
                pushMessageDto.setType(PushMessageType.insertAudioWaitGen);
                break;
            case KEYWORD:
                pushMessageDto.setType(PushMessageType.keywordWaitGen);
                break;
            case USER_ENTER:
                pushMessageDto.setType(PushMessageType.userEnterWaitGen);
                break;
            case RANDOM_AUDIO:
                pushMessageDto.setType(PushMessageType.randomAudioWaitGen);
                break;
            default:
                break;
        }
        if (pushMessageDto.getType() != null) {
            SseEmitterServerUtils.sendMessage(dto.getChannelId(), pushMessageDto);
        }

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        File saveFile = new File(dto.getGenerateAudioPath());
        File parentDir = saveFile.getParentFile();
        if (parentDir != null && !parentDir.exists()) {
            boolean dirsCreated = parentDir.mkdirs(); // 创建所有缺失的父目录
            if (!dirsCreated) {
                throw new RuntimeException("无法创建目录: " + parentDir.getAbsolutePath());
            }
        }

        //根据playerType动态获取ttsUrl
        ModelHandler handler = ModelFactory.getHandler(dto.getPlayerType(), sysConfigService, bvConfigService, modelPath, sovitsUrl, gptUrl);
        String realTtsUrl = ttsUrl;
        if (SingleDoubleModelType.COMPATIBLE.equals(byCode)) {
            realTtsUrl = ttsUrl9881;
        }
        String realUrl = realTtsUrl.replace("port", handler.getRealPort());

        textToSpeechDto.setPromptText(sysConfigService.getConfigValueByKey(handler.getPromptTextKey()));
        textToSpeechDto.setRefAudioPath(sysConfigService.getConfigValueByKey(handler.getRefAudioPathKey()));

        try {
            String audioFilePath = RestUtils.postAudio(realUrl, objectMapper.writeValueAsString(textToSpeechDto), new HashMap<>(), dto.getGenerateAudioPath());
            if (audioFilePath == null) {
                log.error("音频生成失败");
                if (isStart.get() && !LiveRoomStatusType.playing.getCode().equals(bvAudioPlayService.getLiveRoomStatus())) {
                    bvAudioPlayService.updateStartLiveStep(StartLiveStepType.startErr);
                    bvAudioPlayService.stopLive();
                    isStart.set(false);
                }
            }
            textToSpeechVo.setAudioFilePath(audioFilePath);
            textToSpeechVo.setFinalText(textToSpeechDto.getText());
        } catch (Exception e) {
            throw new RuntimeException("音频生成失败", e);
        }

        return textToSpeechVo;
    }

    @Override
    public String batchTts(BatchTtsDto dto) {

        // 指定原始文本文件的根目录（根据实际路径修改）
        Path textRootDir = Paths.get(dto.getInPath());
        // 生成音频文件的根目录（与原目录同级）
        Path audioRootDir = textRootDir.resolveSibling(dto.getOutPath());

        processTextFiles(textRootDir, audioRootDir);
        return "";
    }


    /**
     * 递归处理所有txt文件并生成音频
     *
     * @param textRootDir
     * @param audioRootDir
     */
    public void processTextFiles(Path textRootDir, Path audioRootDir) {
//
//        ConfigDto configDto = bvConfigService.getConfig();
//
//        String refAudioPath = sysConfigService.getConfigValueByKey(BvConstants.REF_AUDIO_PATH);
//        String promptText = sysConfigService.getConfigValueByKey(BvConstants.PROMPT_TEXT);
//
//        try (Stream<Path> fileStream = Files.walk(textRootDir)) {
//            fileStream
//                    .filter(Files::isRegularFile)  // 只处理文件
//                    .filter(path -> path.toString().endsWith(".txt"))  // 过滤txt文件
//                    .forEach(txtFile -> {
//                        try {
//                            // 读取文件内容
//                            List<String> contentList = Files.readAllLines(txtFile, StandardCharsets.UTF_8);
//
//                            if (CollectionUtils.isEmpty(contentList)) {
//                                return;
//                            }
//
//                            for (String text : contentList) {
//                                if (StringUtils.isBlank(text)) {
//                                    continue;
//                                }
//
//                                TextToSpeechFrontDto textToSpeechFrontDto = BvAudioPlayServiceImpl.getTextToSpeechFrontDto(text, configDto.getModelSetting());
//                                textToSpeechFrontDto.setPlayerType(PlayerType.ANCHOR);
//                                String filePath = txtFile.toString().replace(textRootDir.toString(), "");
//
//                                //生成音频文件路径
//                                String tempPath = audioRootDir + File.separator + filePath + File.separator + text.substring(0, 10) + BvConstants.WAV_FORMAT;
//                                textToSpeechFrontDto.setGenerateAudioPath(tempPath);
//                                textToSpeechFrontDto.setPromptText(promptText);
//                                textToSpeechFrontDto.setRefAudioPath(refAudioPath);
//
//                                textToSpeechFrontDto.setScriptType(ScriptType.MAIN_AUDIO);
//                                TextToSpeechVo textToSpeechVo = textToSpeech(textToSpeechFrontDto);
//
//                            }
//                        } catch (IOException e) {
//                            System.err.println("处理失败: " + txtFile);
//                            e.printStackTrace();
//                            throw new RuntimeException(e);
//                        } catch (Exception e) {
//                            throw new RuntimeException(e);
//                        }
//                    });
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
    }
}
